package com.sunl.mall.ali.mq.autoconfigure;


import com.sunl.mall.ali.mq.autoconfigure.annotation.MqBatchConsumer;
import com.sunl.mall.ali.mq.autoconfigure.annotation.MqConsumer;
import com.sunl.mall.ali.mq.autoconfigure.annotation.MqOrderConsumer;
import com.sunl.mall.ali.mq.autoconfigure.config.RocketMqLoggerConfig;
import com.sunl.mall.ali.mq.autoconfigure.scanner.producer.MqOrderProducerBeanScannerRegistrar;
import com.sunl.mall.ali.mq.autoconfigure.scanner.producer.MqProducerBeanScannerRegistrar;
import com.sunl.mall.ali.mq.autoconfigure.scanner.producer.MqTransactionProducerBeanScannerRegistrar;
import com.sunl.mall.ali.mq.consumer.RocketMqConsumerBean;
import com.sunl.mall.ali.mq.producer.RocketMqProducerBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.Set;

/**
 * 只有项目中引用了 {@link RocketMqProducerBean} || {@link RocketMqConsumerBean}才会将当前类注入到spring上下文
 */
@Configuration
@ConditionalOnClass({RocketMqConsumerBean.class, RocketMqProducerBean.class})// 如果有一个class位于类路径上，才会实例化一个Bean
@EnableConfigurationProperties({MqEnvProperties.class})// 如果MqEnvProperties中有@ConfigurationProperties则会被加到spring上下文中
public class RocketMqAutoConfiguration {
    private final MqEnvProperties properties;

    public RocketMqAutoConfiguration(MqEnvProperties properties) {
        this.properties = properties;
    }

    /**
     * 注册普通消息生产者、顺序生产者、事务生产者
     */
    @Import({MqProducerBeanScannerRegistrar.class,
            MqOrderProducerBeanScannerRegistrar.class,
            MqTransactionProducerBeanScannerRegistrar.class})
    public static class MqProducerBeanAutoScannerRegConfiguration {
    }

    /**
     * 设置 ons 日志配置
     *
     * @throws Exception
     */
    @PostConstruct
    public void setOnsLogConfig() {
        RocketMqLoggerConfig mqLoggerConfig = new RocketMqLoggerConfig();
        mqLoggerConfig.setLogLevel(this.properties.getLogLevel());
        mqLoggerConfig.setLogRoot(this.properties.getLogRoot());
        mqLoggerConfig.setLogMaxIndex(this.properties.getLogMaxIndex());
        mqLoggerConfig.afterPropertiesSet();
    }


    /**
     * 根据 配置的消费者包路径 扫描消费者列表
     * <p>
     * 只有配置了{@link MqEnvProperties#BASE_PACKAGES_PROPERTY_NAME}才会扫描业务中定义的Consumer。
     */
    @ConditionalOnProperty(name = {MqEnvProperties.BASE_PACKAGES_PROPERTY_NAME})
    public static class MqProducerAndConsumerBeanAutoScannerRegConfiguration {

        @Bean
        public RocketMqConsumerBeanPostProcessor rocketMqConsumerBeanPostProcessor(Environment environment) {
            Set<String> scanPackagePaths = (Set<String>) environment.getProperty(MqEnvProperties.BASE_PACKAGES_PROPERTY_NAME, Set.class, Collections.emptySet());
            return new RocketMqConsumerBeanPostProcessor(MqConsumer.class, scanPackagePaths);
        }

        @Bean
        public RocketMqConsumerBeanPostProcessor rocketMqOrderConsumerBeanPostProcessor(Environment environment) {
            Set<String> scanPackagePaths = (Set<String>) environment.getProperty(MqEnvProperties.BASE_PACKAGES_PROPERTY_NAME, Set.class, Collections.emptySet());
            return new RocketMqConsumerBeanPostProcessor(MqOrderConsumer.class, scanPackagePaths);
        }

        @Bean
        public RocketMqConsumerBeanPostProcessor rocketMqBatchConsumerBeanPostProcessor(Environment environment) {
            Set<String> scanPackagePaths = (Set<String>) environment.getProperty(MqEnvProperties.BASE_PACKAGES_PROPERTY_NAME, Set.class, Collections.emptySet());
            return new RocketMqConsumerBeanPostProcessor(MqBatchConsumer.class, scanPackagePaths);
        }
    }
}